package com.dq.shiro;

import com.dq.cache.constant.CacheConstant;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Created by 葛文镇
 * email:15258397904@163.com
 * reids缓存得集体实现
 */
public class ShiroRedisCache<K, V> implements Cache<K, V> {
    private static final Logger logger = LoggerFactory.getLogger(ShiroRedisCache.class);
    private RedisTemplate<K, V> redisTemplate;
    private String cacheKey;

    @Value("${dq.redis.timeLive}")
    private long globExpire;

    public ShiroRedisCache(final String name, final RedisTemplate redisTemplate) {
        this.cacheKey = CacheConstant.USER_TOKEN_CACHE_PREFIX + name + ":";
        this.redisTemplate = redisTemplate;
    }

    @Override
    public V get(K key) throws CacheException {
        logger.info("Shiro从缓存中获取数据KEY值[" + key + "]");
        redisTemplate.boundValueOps(getCacheKey(key)).expire(globExpire, TimeUnit.DAYS);
        return redisTemplate.boundValueOps(getCacheKey(key)).get();
    }

    @Override
    public V put(K key, V value) throws CacheException {
        V old = get(key);
        redisTemplate.boundValueOps(getCacheKey(key)).set(value);
        return old;
    }

    @Override
    public V remove(K key) throws CacheException {
        V old = get(key);
        redisTemplate.delete(getCacheKey(key));
        return old;
    }

    @Override
    public void clear() throws CacheException {
        redisTemplate.delete(keys());

    }

    @Override
    public int size() {
        return keys().size();
    }

    @Override
    public Set<K> keys() {
        return redisTemplate.keys(getCacheKey("*"));
    }

    @Override
    public Collection<V> values() {
        Set<K> set = keys();
        List<V> list = new ArrayList<>();
        for (K s : set) {
            list.add(get(s));
        }
        return list;
    }

    private K getCacheKey(Object k) {
        return (K) (this.cacheKey + k);
    }
}
